﻿using System;
using System.Collections;

using zijian666.Abstractions;
using zijian666.Convertor.Base;
using zijian666.Core;
using zijian666.ConvertExtensions;

namespace zijian666.Convertor;

/// <summary>
/// <seealso cref="IList"/> 转换器
/// </summary>
/// <typeparam name="T">集合类型</typeparam>
public class ArrayListConvertor<T> : AllowNullConvertor<T>, IFrom<string, T?>, IFrom<object, T?>, IFrom<object[], T?>
    where T : IList
{

    /// <summary>
    /// 转换器有错误
    /// </summary>
    private readonly bool _error;

    /// <summary>
    /// 转换器默认构造函数
    /// </summary>
    public ArrayListConvertor() => _error = OutputType.MatchType(typeof(ArrayList), typeof(IList)) is not MacthedType.Equals and not MacthedType.Acceptable and not MacthedType.TryCreate;

    /// <inheritdoc />
    public ConvertResult<T?> From(IConvertContext context, string input)
    {
        if (context is null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        if (string.IsNullOrEmpty(input))
        {
            return (T)(object)new ArrayList();
        }

        var arr = context.Settings.Split(input);
        return (T)(object)new ArrayList(arr);
    }

    /// <inheritdoc/>
    public ConvertResult<T?> From(IConvertContext context, object input)
    {
        if (context is null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        if (input is null)
        {
            throw new ArgumentNullException(nameof(input));
        }

        if (_error)
        {
            return ExceptionHelper.InstantiationFail(TypeFriendlyName, context.Settings.CultureInfo, null);
        }
        var enumerator = new KeyValueEnumerator<object, object>(context, input);

        var list = OutputType.IsInterface ? (IList)new ArrayList() : context.Settings.CreateInstance<T>();

        if (enumerator.NotEnumerator)
        {
            _ = list.Add(input);
            return new((T)list);
        }

        while (enumerator.MoveNext())
        {
            _ = list.Add(enumerator.OriginalValue);
        }
        return new((T)list);
    }

    /// <inheritdoc/>
    public ConvertResult<T?> From(IConvertContext context, object[] input)
    {
        if (context is null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        if (input is null)
        {
            throw new ArgumentNullException(nameof(input));
        }

        return From(context, (object)input);
    }
}
